package com.redis.aop;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class LimitIPRequestDisplay {

    @Autowired
    private RedisTemplate redisTemplate;

    @Pointcut("execution(* com.redis.controller.TestController.*.*(..)) && @annotation(com.redis.aop.LimitIPRequest)")
    public void before(){
    }

    @Before("before()")
    public void requestLimit(JoinPoint joinPoint) throws Exception {
        try {
            // 获取HttpRequest
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            HttpServletResponse response = attributes.getResponse();

            // 判断request不能为空
            if (request == null) {
                throw new Exception("HttpServletRequest有误...");
            }

            LimitIPRequest limit = this.getAnnotation(joinPoint);
            if (limit == null) {
                return;
            }

            String ip = request.getRemoteAddr();
            String uri = request.getRequestURI().toString();
            String redisKey = "limit-ip-request:" + uri + ":" + ip;

            // 设置在redis中的缓存，累加1
            Long count = redisTemplate.opsForValue().increment(redisKey);
            System.out.println("redisKey ==="+redisKey + " count=="+ count);
            // 如果该key不存在，则从0开始计算，并且当count为1的时候，设置过期时间
            if (count == 1) {
                redisTemplate.expire(redisKey, limit.timeSecond(), TimeUnit.SECONDS);
            }

            // 如果redis中的count大于限制的次数，则报错
            if (count > limit.limitCounts()) {
                // logger.info("用户IP[" + ip + "]访问地址[" + url + "]超过了限定的次数[" + limit.count() + "]");
                throw new Exception("次数超过限制。。。。。");

            }
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
    }
    /**
     *
     * @Description: 获得注解
     * @param joinPoint
     * @return
     * @throws Exception
     *
     * @author leechenxiang
     * @date 2016年12月14日 下午9:55:32
     */
    private LimitIPRequest getAnnotation(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(LimitIPRequest.class);
        }
        return null;
    }
}